<!doctype html>
<html lang="zh-CN">
<head>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>项目9：字符游戏-智能蛇 | 邵吹水的博客</title>
    <meta property="og:title" content="项目9：字符游戏-智能蛇 - 邵吹水的博客">
    <meta property="og:type" content="article">
        
    <meta property="article:published_time" content='2021-01-05T16:34:11&#43;08:00'>
        
        
    <meta property="article:modified_time" content='2021-01-05T16:34:11&#43;08:00'>
        
    <meta name="Keywords" content="中山大学,shaozhd,吹水,软件工程,C语言,Wikipedia,博客">
    <meta name="description" content="项目9：字符游戏-智能蛇">
        
    <meta name="author" content="shaozhd">
    <meta property="og:url" content="https://shaozhd.gitee.io/post/project9/">
    <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">

    <link rel="stylesheet" href='/css/normalize.css'>
    <link rel="stylesheet" href='/css/style.css'>
    <script type="text/javascript" src="//cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

    
    
    
    
    
    
        <link rel="stylesheet" href='/css/douban.css'>
    
        <link rel="stylesheet" href='/css/other.css'>
    
</head>


<body>
    <header id="header" class="clearfix">
    <div class="container">
        <div class="col-group">
            <div class="site-name ">
                
                    <a id="logo" href="https://shaozhd.gitee.io">
                        邵吹水的博客
                    </a>
                
                <p class="description">一点儿都不想做学渣的软工本科小邵同学</p>
            </div>
            <div>
                <nav id="nav-menu" class="clearfix">
                    <a class="current" href="https://shaozhd.gitee.io">首页</a>
                    
                    <a  href="https://shaozhd.gitee.io/homework/" title="作业">作业</a>
                    
                    <a  href="https://shaozhd.gitee.io/archives/" title="归档">归档</a>
                    
                    <a  href="https://shaozhd.gitee.io/about/" title="关于">关于</a>
                    
                </nav>
            </div>
        </div>
    </div>
</header>

    <div id="body">
        <div class="container">
            <div class="col-group">

                <div class="col-8" id="main">
                    
<div class="res-cons">
    <style type="text/css">
    .post-toc {
        position: fixed;
        width: 200px;
        margin-left: -210px;
        padding: 5px 10px;
        font-family: Athelas, STHeiti, Microsoft Yahei, serif;
        font-size: 12px;
        border: 1px solid rgba(0, 0, 0, .07);
        border-radius: 5px;
        background-color: rgba(255, 255, 255, 0.98);
        background-clip: padding-box;
        -webkit-box-shadow: 1px 1px 2px rgba(0, 0, 0, .125);
        box-shadow: 1px 1px 2px rgba(0, 0, 0, .125);
        word-wrap: break-word;
        white-space: nowrap;
        -webkit-box-sizing: border-box;
        box-sizing: border-box;
        z-index: 999;
        cursor: pointer;
        max-height: 70%;
        overflow-y: auto;
        overflow-x: hidden;
    }

    .post-toc .post-toc-title {
        width: 100%;
        margin: 0 auto;
        font-size: 20px;
        font-weight: 400;
        text-transform: uppercase;
        text-align: center;
    }

    .post-toc .post-toc-content {
        font-size: 15px;
    }

    .post-toc .post-toc-content>nav>ul {
        margin: 10px 0;
    }

    .post-toc .post-toc-content ul {
        padding-left: 20px;
        list-style: square;
        margin: 0.5em;
        line-height: 1.8em;
    }

    .post-toc .post-toc-content ul ul {
        padding-left: 15px;
        display: none;
    }

    @media print,
    screen and (max-width:1057px) {
        .post-toc {
            display: none;
        }
    }
</style>
<div class="post-toc" style="position: absolute; top: 188px;">
    <h2 class="post-toc-title">文章目录</h2>
    <div class="post-toc-content">
        <nav id="TableOfContents"></nav>
    </div>
</div>
<script type="text/javascript">
    $(document).ready(function () {
        var postToc = $(".post-toc");
        if (postToc.length) {
            var leftPos = $("#main").offset().left;
            if(leftPos<220){
                postToc.css({"width":leftPos-10,"margin-left":(0-leftPos)})
            }

            var t = postToc.offset().top - 20,
                a = {
                    start: {
                        position: "absolute",
                        top: t
                    },
                    process: {
                        position: "fixed",
                        top: 20
                    },
                };
            $(window).scroll(function () {
                var e = $(window).scrollTop();
                e < t ? postToc.css(a.start) : postToc.css(a.process)
            })
        }
    })
</script>
    <article class="post">
        <header>
            <h1 class="post-title">项目9：字符游戏-智能蛇</h1>
        </header>
        <date class="post-meta meta-date">
            2021年1月5日
        </date>
        
        
        <div class="post-meta">
            <span id="busuanzi_container_page_pv">|<span id="busuanzi_value_page_pv"></span><span>
                    阅读</span></span>
        </div>
        
        
        <div class="post-content">
            <h1 id="使用的工具">使用的工具</h1>
<p>Google Chrome 用作网页浏览工具</p>
<h1 id="一实验目的">一、实验目的</h1>
<p>了解 算法 与 “智能” 的关系 通过算法赋予蛇智能 了解 Linux IO 设计的控制</p>
<h1 id="二实验环境">二、实验环境</h1>
<p>Linux Only. 你可以选择 Unbutu、Centos 等发行版。 建议编辑环境 Vim 或 Vscode, 编译 gcc 第一次使用 Linux，建议使用虚拟机。可以使用其他同学准备好的 Vbox 镜像</p>
<h1 id="三控制输入输出设备">三、控制输入/输出设备</h1>
<p>你知道为什么一行代码要控制在80（字符）列以内？ 原因是 … 原来历史上读程序的卡片机只能读80个字符。当然，超过 80 个字符也打不出来阅读了。</p>
<p>那么一个语句超过 80 个字符怎么办？ 续行符…</p>
<p>言归正传，早期的输出设备显示器、打印机，输入设备键盘（打字机）都是80列行缓冲顺序输入和输出设备。即你打印文件时，打印机必须等收到行结束符，打印机才会动作。然而，输入/输出随着应用需求不断进化，字符界面控制与管理已经非常标准化了。</p>
<ol>
<li>VT 100 终端标准
在字符终端上完成“清屏”“修改光标位置”“设置字符前景和背景色”等操作，是通过输出 esc序列实现的。对于 VT100 终端, printf(&quot;\033[2J&rdquo;) 就实现了清屏。</li>
</ol>
<pre><code> #include &lt;stdio.h&gt;
    #include &lt;math.h&gt;
    #include &lt;unistd.h&gt;
    #define PI  3.14
    #define SIN_AMPLITUDE  20      
    #define DELAY_TIME  100000  
    #define TRIANGLE  360.0   
    #define Y_NUMBER_BEGIN_LINE  3
    #define SIN_GRAPH_BEGIN_LINE (Y_NUMBER_BEGIN_LINE+1)
    
    int main(int argc, char* argv[]){
    
        int i = 0;    
        int lineNumber = 0;    
        int offsetCenter = 0;    
        int nextInitAngle = 0;
        double currentInitAngle = 0;    
        double currentInitradian = 0;    
        printf(&quot;\033[2J&quot;);
        printf(&quot;\033[1;1H                       | SinDemo |\t&quot;);
        printf(&quot;\033[%d;1H\t&quot;, Y_NUMBER_BEGIN_LINE);
        for (i = 0; i &lt; SIN_AMPLITUDE*2; i++) 
            printf(&quot;%d&quot;, i%10);
        printf(&quot;\n&quot;);
        while(1){
            i = 0;        
            offsetCenter = 0;       
            lineNumber = 0;      
            currentInitradian = 0;
            currentInitAngle = nextInitAngle;
            nextInitAngle += TRIANGLE/SIN_AMPLITUDE;
            printf(&quot;\033[%d;1H&quot;, SIN_GRAPH_BEGIN_LINE);
            while(1){
                if(lineNumber == SIN_AMPLITUDE){
                    printf(&quot;\033[%d;1H%04d\t&quot;, lineNumber+SIN_GRAPH_BEGIN_LINE, lineNumber);
                    for (i = 0; i &lt; SIN_AMPLITUDE*2; i++)
                        i == SIN_AMPLITUDE ? printf(&quot;V X&quot;) : printf(&quot; &quot;);    
                    break;
                }
    
    
                currentInitAngle = ((int)currentInitAngle)%((int)TRIANGLE);
                currentInitradian = currentInitAngle/(TRIANGLE/2)*PI;    
    
                offsetCenter = (int)(sin(currentInitradian)*SIN_AMPLITUDE);                
                printf(&quot;\033[%d;1H%04d&quot;, lineNumber+SIN_GRAPH_BEGIN_LINE, lineNumber);
                printf(&quot;\t&quot;);
                if(lineNumber == 0){
                    for (i = 0; i &lt; SIN_AMPLITUDE*2; i++){
                        if(i == offsetCenter+SIN_AMPLITUDE)
                            printf(&quot;@&quot;);
                    }
                    printf(&quot;-&gt; Y\n&quot;);
                } else { 
                    for (i = 0; i &lt; SIN_AMPLITUDE*2; i++){
                        if(i == (offsetCenter+SIN_AMPLITUDE)){
                            printf(&quot;*&quot;);
                        }else if(i == SIN_AMPLITUDE){
                            printf(&quot;|&quot;);
                        }else{
                            (((i &gt; SIN_AMPLITUDE) &amp;&amp; (i &lt; SIN_AMPLITUDE+offsetCenter)) || \
                                ((i &lt; SIN_AMPLITUDE) &amp;&amp; (i &gt; SIN_AMPLITUDE+offsetCenter))) \
                                    ? printf(&quot;-&quot;) : printf(&quot; &quot;);
                        }
                        if(i == (SIN_AMPLITUDE*2-1)) 
                            printf(&quot;\n&quot;);
                    }
                }
                currentInitAngle += TRIANGLE/SIN_AMPLITUDE;      
                lineNumber++;                                    
            }
            printf(&quot;\n&quot;);
            usleep(DELAY_TIME);
        }
        return 0;
    }
</code></pre><p>
        <img class="mx-auto" alt="LocalPicture" src="../pic/project/9_1.png" />   
    </p>
<ol start="2">
<li>实现 kbhit()
检测 tty 输入的程序，远远超出了入门者的能力，你只需要会运行该程序，并将 snake 代码融入该代码。</li>
</ol>
<pre><code>#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;sys/time.h&gt;
#include &lt;sys/types.h&gt;
#include &lt;unistd.h&gt;
#include &lt;termios.h&gt;
#include &lt;unistd.h&gt;

static struct termios ori_attr, cur_attr;

static __inline 
int tty_reset(void)
{
        if (tcsetattr(STDIN_FILENO, TCSANOW, &amp;ori_attr) != 0)
                return -1;

        return 0;
}


static __inline
int tty_set(void)
{
        
        if ( tcgetattr(STDIN_FILENO, &amp;ori_attr) )
                return -1;
        
        memcpy(&amp;cur_attr, &amp;ori_attr, sizeof(cur_attr) );
        cur_attr.c_lflag &amp;= ~ICANON;
        cur_attr.c_lflag &amp;= ~ECHO;
        cur_attr.c_cc[VMIN] = 1;
        cur_attr.c_cc[VTIME] = 0;

        if (tcsetattr(STDIN_FILENO, TCSANOW, &amp;cur_attr) != 0)
                return -1;

        return 0;
}

static __inline
int kbhit(void) 
{
                
        fd_set rfds;
        struct timeval tv;
        int retval;

        FD_ZERO(&amp;rfds);
        FD_SET(0, &amp;rfds);
        tv.tv_sec  = 0;
        tv.tv_usec = 0;

        retval = select(1, &amp;rfds, NULL, NULL, &amp;tv);
        if (retval == -1) {
                perror(&quot;select()&quot;);
                return 0;
        } else if (retval)
                return 1;
        else
                return 0;
        return 0;
}

int main()
{
        int tty_set_flag;
        tty_set_flag = tty_set();

        printf(&quot;pressed `q` to quit!\n&quot;);
        while(1) {

                if( kbhit() ) {
                        const int key = getchar();
                        printf(&quot;%c pressed\n&quot;, key);
                        if(key == 'q')
                                break;
                } else {(stderr, &quot;&lt;no key detected&gt;\n&quot;);
                }
        }

        if(tty_set_flag == 0) 
                tty_reset();
        return 0;
}
</code></pre><h1 id="四编写智能算法">四、编写智能算法</h1>
<p>编写人工智能程序，使得 snake 每秒自动走一步。</p>
<ol>
<li>程序要求
请修改初始化字符矩阵，或者通过文件读入地图。地图中有一些你设定的障碍物（墙） 请实现如下算法决定蛇行走的方向 思考：一个长度为5的障碍物能困死该自动跑的蛇吗？</li>
</ol>
<p>决定蛇行走的方向函数的伪代码
// Hx,Hy: 头的位置 // Fx,Fy：食物的位置 function whereGoNext(Hx,Hy,Fx,Fy) { // 用数组movable[3]={“a”,”d”,”w”,”s”} 记录可走的方向 // 用数组distance[3]={0,0,0,0} 记录离食物的距离 // 分别计算蛇头周边四个位置到食物的距离。H头的位置，F食物位置 // 例如：假设输入”a” 则distance[0] = |Fx – (Hx-1)| + |Fy – Hy| // 如果 Hx-1，Hy 位置不是Blank，则 distance[0] = 9999 // 选择distance中存最小距离的下标p，注意最小距离不能是9999 // 返回 movable[p] }</p>
<ol start="2">
<li>智能蛇的程序框架</li>
</ol>
<pre><code>输出字符矩阵
WHILE not 游戏结束 DO
    wait(time)
    ch＝whereGoNext(Hx,Hy,Fx,Fy)
    CASE ch DO
    ‘A’:左前进一步，break 
    ‘D’:右前进一步，break    
    ‘W’:上前进一步，break    
    ‘S’:下前进一步，break    
    END CASE
    输出字符矩阵
END WHILE
输出 Game Over!!! 
</code></pre><ol start="3">
<li>函数设计</li>
</ol>
<p>
        <img class="mx-auto" alt="9_2" src="../pic/project/9_2.png" />   
    </p>

        </div>

        
<div class="post-archive">
    <ul class="post-copyright">
        <li><strong>原文作者：</strong><a rel="author" href="https://shaozhd.gitee.io">shaozhd</a></li>
        <li style="word-break:break-all"><strong>原文链接：</strong><a href="https://shaozhd.gitee.io/post/project9/">https://shaozhd.gitee.io/post/project9/</a></li>
        <li><strong>版权声明：</strong>本作品采用<a rel="license" href="https://zh.wikipedia.org/wiki/%e5%85%b1%e4%ba%a7%e4%b8%bb%e4%b9%89">我自己看一遍的方法</a>进行许可，非商业转载请注明出处（作者，原文链接），商业转载请联系作者获得授权。</li>
    </ul>
</div>
<br/>



        

<div class="post-archive">
    <h2>See Also</h2>
    <ul class="listing">
        
        <li><a href="/post/wiki10/">【补交】作业10</a></li>
        
        <li><a href="/post/wiki8/">【补交】作业8</a></li>
        
        <li><a href="/post/wiki9/">【补交】作业9</a></li>
        
        <li><a href="/post/project4/">【补交】项目4</a></li>
        
        <li><a href="/post/project5/">【补交】项目5</a></li>
        
    </ul>
</div>


        <div class="post-meta meta-tags">
            
            没有标签
            
        </div>
    </article>
    
    <div id="disqus_thread"></div>
<script type="application/javascript">
    var disqus_config = function () {
    
    
    
    };
    (function() {
        if (["localhost", "127.0.0.1"].indexOf(window.location.hostname) != -1) {
            document.getElementById('disqus_thread').innerHTML = 'Disqus comments not available by default when the website is previewed locally.';
            return;
        }
        var d = document, s = d.createElement('script'); s.async = true;
        s.src = '//' + "yourdiscussshortname" + '.disqus.com/embed.js';
        s.setAttribute('data-timestamp', +new Date());
        (d.head || d.body).appendChild(s);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="https://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

    
    
</div>

                    <footer id="footer">
    <div>
        &copy; 2021 <a href="https://shaozhd.gitee.io">邵吹水的博客 By shaozhd</a>
        
    </div>
    <br />
    <div>
        <div class="github-badge">
            <a href="https://gohugo.io/" target="_black" rel="nofollow"><span class="badge-subject">Powered by</span><span class="badge-value bg-blue">Hugo</span></a>
        </div>
        <div class="github-badge">
            <a href="https://www.flysnow.org/" target="_black"><span class="badge-subject">Design by</span><span class="badge-value bg-brightgreen">飞雪无情</span></a>
        </div>
        <div class="github-badge">
            <a href="https://github.com/flysnow-org/maupassant-hugo" target="_black"><span class="badge-subject">Theme</span><span class="badge-value bg-yellowgreen">Maupassant</span></a>
        </div>
    </div>
</footer>


    
    <script type="text/javascript">
        window.MathJax = {
            tex2jax: {
                inlineMath: [['$', '$']],
                processEscapes: true
                }
            };
    </script>
    <script src='https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML' async></script>

<a id="rocket" href="#top"></a>
<script type="text/javascript" src='/js/totop.js?v=0.0.0' async=""></script>



    <script type="text/javascript" src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" async></script>




    <script src='/js/douban.js'></script>


                </div>

                <div id="secondary">
    <section class="widget">
        <form id="search" action='https://shaozhd.gitee.io/search/' method="get" accept-charset="utf-8" target="_blank" _lpchecked="1">
      
      <input type="text" name="q" maxlength="20" placeholder="Search">
      <input type="hidden" name="sitesearch" value="https://shaozhd.gitee.io">
      <button type="submit" class="submit icon-search"></button>
</form>
    </section>
    
    <section class="widget">
        <h3 class="widget-title">最近文章</h3>
<ul class="widget-list">
    
    <li>
        <a href="https://shaozhd.gitee.io/post/wiki10/" title="【补交】作业10">【补交】作业10</a>
    </li>
    
    <li>
        <a href="https://shaozhd.gitee.io/post/wiki8/" title="【补交】作业8">【补交】作业8</a>
    </li>
    
    <li>
        <a href="https://shaozhd.gitee.io/post/wiki9/" title="【补交】作业9">【补交】作业9</a>
    </li>
    
    <li>
        <a href="https://shaozhd.gitee.io/post/project4/" title="【补交】项目4">【补交】项目4</a>
    </li>
    
    <li>
        <a href="https://shaozhd.gitee.io/post/project5/" title="【补交】项目5">【补交】项目5</a>
    </li>
    
    <li>
        <a href="https://shaozhd.gitee.io/post/project6/" title="【补交】项目6">【补交】项目6</a>
    </li>
    
    <li>
        <a href="https://shaozhd.gitee.io/post/project7/" title="【补交】项目7">【补交】项目7</a>
    </li>
    
    <li>
        <a href="https://shaozhd.gitee.io/post/project9/" title="项目9：字符游戏-智能蛇">项目9：字符游戏-智能蛇</a>
    </li>
    
    <li>
        <a href="https://shaozhd.gitee.io/post/project8/" title="项目8：字符游戏-贪吃蛇">项目8：字符游戏-贪吃蛇</a>
    </li>
    
    <li>
        <a href="https://shaozhd.gitee.io/post/wiki7/" title="使用维基百科(Wikipedia)解释名词VII及其解答题">使用维基百科(Wikipedia)解释名词VII及其解答题</a>
    </li>
    
</ul>
    </section>

    

    <section class="widget">
        <h3 class="widget-title"><a href="/categories">分类</a></h3>
<ul class="widget-list">
    
</ul>
    </section>

    <section class="widget">
        <h3 class="widget-title"><a href="/tags">标签</a></h3>
<div class="tagcloud">
    
</div>
    </section>

    

    <section class="widget">
        <h3 class="widget-title">其它</h3>
        <ul class="widget-list">
            <li><a href="https://shaozhd.gitee.io/index.xml">文章 RSS</a></li>
        </ul>
    </section>
</div>
            </div>
        </div>
    </div>
</body>

</html>